package com.qk.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.qk.common.PageResult;
import com.qk.dto.BusinessQueryDTO;
import com.qk.dto.BusinessUpdateDTO;
import com.qk.entity.Business;
import com.qk.entity.BusinessTrackRecord;
import com.qk.entity.Customer;
import com.qk.enums.BusinessEvent;
import com.qk.enums.BusinessState;
import com.qk.mapper.BusinessMapper;
import com.qk.mapper.BusinessTrackRecordMapper;
import com.qk.mapper.CustomerMapper;
import com.qk.service.BusinessService;
import com.qk.state.service.BusinessStateMachineService;
import com.qk.utils.CurrentUserHoler;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;


/**
 * @author 28188
 */
@Service
public class BusinessServiceImpl extends ServiceImpl<BusinessMapper, Business> implements BusinessService {

    @Autowired
    private BusinessTrackRecordMapper businessTrackRecordMapper;
    @Autowired
    private CustomerMapper customerMapper;
    @Autowired
    private BusinessStateMachineService businessStateMachineService;

    @Override
    public PageResult<Business> pageBusinesses(BusinessQueryDTO businessQueryDTO) {
        Page<Business> page = this.baseMapper.listBusinesses(new Page<>(businessQueryDTO.getPage(), businessQueryDTO.getPageSize()), businessQueryDTO);
        return new PageResult<>(page.getTotal(), page.getRecords());
    }

    @Override
    public Business getBusinessById(Integer id) {
        return this.baseMapper.selectBusinessById(id);
    }

    /**
     * 根据ID更新业务信息，并可能添加跟踪记录
     *
     * @param businessUpdateDTO 包含更新业务信息的DTO对象
     * @Transactional 确保方法执行过程中出现异常时进行回滚，rollbackFor = Exception.class表示对所有异常都进行回滚
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void updateBusinessById(BusinessUpdateDTO businessUpdateDTO) {
        BusinessState newState = businessStateMachineService.sendEvent(businessUpdateDTO.getId(), BusinessEvent.START_FOLLOWUP);
        int num = newState.getCode();
        businessUpdateDTO.setUpdateTime(LocalDateTime.now());
        businessUpdateDTO.setStatus(newState.getCode());
        // 更新业务基本信息
        this.baseMapper.updateBusinessById(businessUpdateDTO);
        // 检查是否有跟踪记录信息需要添加
        if (hasTrackRecordInfo(businessUpdateDTO)) {
            // 创建新的业务跟踪记录对象
            BusinessTrackRecord businessTrackRecord = new BusinessTrackRecord();
            // 设置业务ID
            businessTrackRecord.setBusinessId(businessUpdateDTO.getId());
            // 设置当前操作用户ID
            businessTrackRecord.setUserId(CurrentUserHoler.getCurrentUser());
            // 设置跟踪状态
            businessTrackRecord.setTrackStatus(businessUpdateDTO.getTrackStatus());
            // 设置关键事项
            businessTrackRecord.setKeyItems(businessUpdateDTO.getKeyItems());
            // 设置下次跟进时间
            businessTrackRecord.setNextTime(businessUpdateDTO.getNextTime());
            // 设置记录内容
            businessTrackRecord.setRecord(businessUpdateDTO.getRecord());
            // 设置创建时间为当前时间
            businessTrackRecord.setCreateTime(LocalDateTime.now());
            // 插入新的跟踪记录
            businessTrackRecordMapper.insert(businessTrackRecord);
        }
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void backBusiness(Integer id) {
        BusinessState newState = businessStateMachineService.sendEvent(id, BusinessEvent.RECYCLE);
        Business business = new Business();
        business.setId(id);
        business.setStatus(newState.getCode());
        business.setUpdateTime(LocalDateTime.now());
        this.baseMapper.updateById(business);

        BusinessTrackRecord businessTrackRecord = new BusinessTrackRecord();
        businessTrackRecord.setBusinessId(id);
        businessTrackRecord.setUserId(CurrentUserHoler.getCurrentUser());
        businessTrackRecord.setTrackStatus(2);
        businessTrackRecord.setCreateTime(LocalDateTime.now());
        businessTrackRecordMapper.insert(businessTrackRecord);
    }

    @Override
    public void toCustomer(Integer id) {
        BusinessState newState = businessStateMachineService.sendEvent(id, BusinessEvent.CONVERT_TO_CUSTOMER);
        Business business = new Business();
        business.setId(id);
        business.setStatus(newState.getCode());
        business.setUpdateTime(LocalDateTime.now());
        this.baseMapper.updateById(business);

        Customer customer = new Customer();
        Business businessTemp = this.baseMapper.selectBusinessById(id);
        BeanUtils.copyProperties(businessTemp, customer, "id", "createTime", "updateTime");
        customer.setBusinessId(businessTemp.getId());
        customer.setCreateTime(LocalDateTime.now());
        customer.setUpdateTime(LocalDateTime.now());
        customerMapper.insert(customer);
    }

    @Override
    public void assignBusiness(Integer businessId, Integer userId) {
        BusinessState nweState = businessStateMachineService.sendEvent(businessId, BusinessEvent.ASSIGN);
        Business business = new Business();
        business.setId(businessId);
        business.setStatus(nweState.getCode());
        business.setUserId(userId);
        business.setUpdateTime(LocalDateTime.now());
        this.baseMapper.updateById(business);
    }

    @Override
    public void saveBusiness(Business business) {
        business.setCreateTime(LocalDateTime.now());
        business.setUpdateTime(LocalDateTime.now());
        business.setStatus(BusinessState.UNASSIGNED.getCode());
        this.baseMapper.insert(business);
    }

    @Override
    public PageResult<Business> pagePool(BusinessQueryDTO businessQueryDTO) {

        LambdaQueryWrapper<Business> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Business::getStatus, BusinessState.RECYCLED.getCode())
                .eq(businessQueryDTO.getBusinessId() != null, Business::getId, businessQueryDTO.getBusinessId())
                .eq(businessQueryDTO.getPhone() != null && !businessQueryDTO.getPhone().isEmpty(), Business::getPhone, businessQueryDTO.getPhone())
                .eq(businessQueryDTO.getName() != null && !businessQueryDTO.getName().isEmpty(), Business::getName, businessQueryDTO.getName())
                .eq(businessQueryDTO.getSubject() != null, Business::getSubject, businessQueryDTO.getSubject());
        Page<Business> page = new Page<>(businessQueryDTO.getPage(), businessQueryDTO.getPageSize());
        Page<Business> result = this.baseMapper.selectPage(page, queryWrapper);
        return new PageResult<>(result.getTotal(), result.getRecords());
    }


    private boolean hasTrackRecordInfo(BusinessUpdateDTO businessUpdateDTO) {
        return businessUpdateDTO.getTrackStatus() != null && businessUpdateDTO.getTrackStatus() > 0
                || businessUpdateDTO.getKeyItems() != null && !businessUpdateDTO.getKeyItems().isEmpty()
                || businessUpdateDTO.getRecord() != null && !businessUpdateDTO.getRecord().isEmpty();
    }
}
